package com.irdstudio.efp.esb.api.rest.sed.credit;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.irdstudio.basic.framework.core.constant.ESBConstant;
import com.irdstudio.basic.framework.core.constant.EsbRetCodeStandard;
import com.irdstudio.basic.framework.core.exception.BizException;
import com.irdstudio.basic.framework.core.util.DateUtility;
import com.irdstudio.basic.framework.core.util.RandomCodeUtils;
import com.irdstudio.basic.framework.core.util.StringUtil;
import com.irdstudio.basic.framework.core.util.TraceUtil;
import com.irdstudio.basic.sequence.service.facade.SequenceService;
import com.irdstudio.efp.basic.framework.mq.client.producer.MQProducerMessageClient;
import com.irdstudio.efp.basic.framework.mq.constant.TagEnums;
import com.irdstudio.efp.basic.framework.mq.constant.TopicEnums;
import com.irdstudio.efp.console.common.ConsoleConstant;
import com.irdstudio.efp.console.common.psd.PsdConstantSet;
import com.irdstudio.efp.ctr.service.facade.CtrLoanContService;
import com.irdstudio.efp.ctr.service.vo.CtrLoanContVO;
import com.irdstudio.efp.esb.api.bean.sed.credit.req.ReqContractSignBean;
import com.irdstudio.efp.esb.api.bean.sed.credit.resp.RespSedCreditBean;
import com.irdstudio.efp.esb.api.common.EsbRespServiceBeanCreator;
import com.irdstudio.efp.esb.common.constant.EsbBizEnums;
import com.irdstudio.efp.esb.common.constant.EsbSysHeadEnums;
import com.irdstudio.efp.esb.common.server.req.EsbReqServiceBean;
import com.irdstudio.efp.esb.common.server.resp.EsbRespServiceBean;
import com.irdstudio.efp.esb.service.bo.req.sed.letter.ReqSedLetterBean;
import com.irdstudio.efp.esb.service.facade.sed.letter.SedLetterInformService;
import com.irdstudio.efp.limit.service.facade.LmtPrdContService;
import com.irdstudio.efp.limit.service.vo.LmtPrdContVO;
import com.irdstudio.efp.nls.common.constant.NlsApplyInfoEnums;
import com.irdstudio.efp.nls.common.constant.PrdAdaptedSoltEnums;
import com.irdstudio.efp.nls.common.constant.QueueTaskEnums;
import com.irdstudio.efp.nls.service.facade.psd.PsdSxCtrSignatureService;
import com.irdstudio.efp.nls.service.facade.queue.NlsProcessBizService;
import com.irdstudio.efp.nls.service.facade.sx.NlsCreditInfoService;
import com.irdstudio.efp.nls.service.vo.psd.SxCtrInfo;
import com.irdstudio.efp.nls.service.vo.queue.NlsProcessBizVO;
import com.irdstudio.efp.nls.service.vo.sx.NlsCreditInfoVO;
import org.apache.rocketmq.common.message.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import java.util.Optional;

/**
* 普税贷产品对税e贷产品的此部分代码做了复用
* 说明：为了保证功能的复用性、提升开发的工作效率，对该代码进行了复用
* 评估是否会影响线上功能：否
* 评估时间：2020/5/25
* 处理方案：保留复用
*/
@RestController
@RequestMapping("/esb")
public class ContractSignedController {

    private static Logger logger = LoggerFactory.getLogger(ContractSignedController.class);

    @Autowired
    private PsdSxCtrSignatureService psdSxCtrSignatureService;

    @ModelAttribute("esbReqServiceBean")
    public EsbReqServiceBean getReqEsbHeadBean(HttpServletRequest request) {
        logger.info("获取ESB请求对象，校验 ESB请求系统头和请求应用头对象开始");
        EsbReqServiceBean esbReqServiceBean = (EsbReqServiceBean) request.getAttribute("esbReqServiceBean");
        return esbReqServiceBean;
    }

    @ModelAttribute("reqContractSignBean")
    public ReqContractSignBean getReqEsbBodyBean(HttpServletRequest request) {
        logger.info("获取调额结果查询服务接口请求对象，校验调额结果查询服务接口请求体对象开始");
        String esbReqBody = (String) request.getAttribute("esbReqBody");
        return JSONObject.parseObject(esbReqBody, ReqContractSignBean.class);
    }

    @PostMapping("/SERVICE_30220008_03")
    public EsbRespServiceBean doRecv(@Validated @ModelAttribute("esbReqServiceBean") EsbReqServiceBean esbReqServiceBean, BindingResult br1,
                                     @Validated @ModelAttribute("reqContractSignBean") ReqContractSignBean reqContractSignBean, BindingResult br2, Exception exception) {
        try {
            // 1. 通过切面校验请求参数是否正确，如不正确则返回错误信息
            if (Objects.nonNull(exception)) {
                throw exception;
            }
            //封装信息
            SxCtrInfo sxCtrInfo = setSxctrinfo(reqContractSignBean);
            //普税贷合同签订
            final String[] strings = psdSxCtrSignatureService.sxSignature(sxCtrInfo);
            //如果成功则下发短信通知客户
            if (strings[0].equals(ESBConstant.SUCCESS)) {
                sendCtrMsg(reqContractSignBean.getCrdAgrmNo(),reqContractSignBean.getCtcTelNo());
            }
            return EsbRespServiceBeanCreator.buildesbRespServiceBean(
                    esbReqServiceBean,
                    JSON.toJSONString(buildRespLoanAdjustLimitBean(strings[0], strings[1], reqContractSignBean.getCrdtAppFlowNo())),
                    (strings[0].equals(ESBConstant.SUCCESS))?(EsbSysHeadEnums.RetStEnum.SUCCESS.getCode()):(EsbSysHeadEnums.RetStEnum.FAILURE.getCode()),
                    strings[0],
                    strings[1]
            );
        } catch (BizException e) {
            logger.error("***********调用合同要素查询接口处理失败," + e.getMessage() + "**************");
            return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean,
                    JSONObject.toJSONString(buildRespLoanAdjustLimitBean(e.getErrorCode(), e.getMessage(), reqContractSignBean.getCrdtAppFlowNo())),
                    EsbSysHeadEnums.RetStEnum.FAILURE.getCode(),
                    e.getErrorCode(),
                    e.getMessage());
        } catch (Exception e) {
            logger.error("***********合同签订服务接口处理失败!" + e.getMessage() + "***********");
            return EsbRespServiceBeanCreator.buildesbRespServiceBean(
                    esbReqServiceBean,
                    JSON.toJSONString(buildRespLoanAdjustLimitBean(EsbRetCodeStandard.OTHERS_EXCEPTION.getValue(), e.getMessage(), reqContractSignBean.getCrdtAppFlowNo())),
                    EsbSysHeadEnums.RetStEnum.FAILURE.getCode(),
                    EsbRetCodeStandard.OTHERS_EXCEPTION.getValue(),
                    e.getMessage()
            );
        } finally {
            logger.info("***********合同签订服务结束......授信申请流水号为：" + reqContractSignBean.getCrdtAppFlowNo() + "***********");
        }
    }

    private SxCtrInfo setSxctrinfo(@ModelAttribute("reqContractSignBean") @Validated ReqContractSignBean reqContractSignBean) {
        SxCtrInfo sxCtrInfo = new SxCtrInfo();
        sxCtrInfo.setCrdtAppFlowNo(reqContractSignBean.getCrdtAppFlowNo());
        sxCtrInfo.setCrdAgrmNo(reqContractSignBean.getCrdAgrmNo());
        sxCtrInfo.setBrchNm(reqContractSignBean.getBrchNm());
        sxCtrInfo.setOrgSite(reqContractSignBean.getOrgSite());
        sxCtrInfo.setOrgPstCd(reqContractSignBean.getOrgPstCd());
        sxCtrInfo.setOrgFax(reqContractSignBean.getOrgFax());
        sxCtrInfo.setCorpTel(reqContractSignBean.getCorpTel());
        sxCtrInfo.setCustNm(reqContractSignBean.getCustNm());
        sxCtrInfo.setCertTp(reqContractSignBean.getCertTp());
        sxCtrInfo.setCertNo(reqContractSignBean.getCertNo());
        sxCtrInfo.setResdntAddr(reqContractSignBean.getResdntAddr());
        sxCtrInfo.setPstcd(reqContractSignBean.getPstcd());
        sxCtrInfo.setClnttFax(reqContractSignBean.getClnttFax());
        sxCtrInfo.setCtcTelNo(reqContractSignBean.getCtcTelNo());
        sxCtrInfo.setEmail(reqContractSignBean.getEmail());
        sxCtrInfo.setSmlLoanAmt(new BigDecimal(reqContractSignBean.getRMBLwrcs()));
        sxCtrInfo.setLrgLoanAmt(reqContractSignBean.getRMBCptl());
        return sxCtrInfo;
    }

/**
 @PostMapping("/SERVICE_30220008_03") public EsbRespServiceBean doRecv(@Validated @ModelAttribute("esbReqServiceBean") EsbReqServiceBean esbReqServiceBean, BindingResult br1,
 @Validated @ModelAttribute("reqContractSignBean") ReqContractSignBean reqContractSignBean, BindingResult br2, Exception exception) {

 String lmtApplySeq = reqContractSignBean.getCrdtAppFlowNo();
 String lmtContNo = reqContractSignBean.getCrdAgrmNo();
 String smlLoanAmt = reqContractSignBean.getSmlLoanAmt();
 String globalSerno = esbReqServiceBean.getSysHead().getGlblSrlNo();
 TraceUtil.setTraceId(globalSerno);
 logger.info("***********合同签订服务开始......授信申请流水号为：" + lmtApplySeq + "***********");
 try {
 // 1. 通过切面校验请求参数是否正确，如不正确则返回错误信息
 if (Objects.nonNull(exception)) {
 throw exception;
 }

 if (StringUtil.isNullorBank(lmtApplySeq)) {
 throw new BizException(EsbRetCodeStandard.JKYDCSJYBTG.getValue(), "需要上送授信申请流水号!");
 }
 if (StringUtil.isNullorBank(lmtContNo)) {
 throw new BizException(EsbRetCodeStandard.JKYDCSJYBTG.getValue(), "需要上送授信协议编号!");
 }
 if (!StringUtil.isNumber(smlLoanAmt)) {
 throw new BizException(EsbRetCodeStandard.JKYDCSJYBTG.getValue(), "金额应输入数字，请检查!");
 }
 //查询授信申请表，获取信息，根据授信状态判断后续处理
 NlsCreditInfoVO nlsCreditInfoVO = getApprvSts(lmtApplySeq);
 if (Objects.isNull(nlsCreditInfoVO)) {
 throw new Exception("未查询到该笔授信，请检查！");
 }
 logger.info("******************根据流水号查询到的授信信息为：" + nlsCreditInfoVO.toString() + "******************");
 logger.info("******************授信状态为：" + nlsCreditInfoVO.getApprvSts() + "******************");

 //普税贷合同签订
 if (PsdConstantSet.prdId.equals(nlsCreditInfoVO.getPrdId())) {
 final String[] strings = psdSxCtrSignatureService.sxSignature(nlsCreditInfoVO.getLmtApplySeq());
 //下发短信通知客户
 if (strings[0].equals(ESBConstant.SUCCESS)){
 sendCtrMsg(nlsCreditInfoVO);
 }
 return EsbRespServiceBeanCreator.buildesbRespServiceBean(
 esbReqServiceBean,
 JSON.toJSONString(buildRespLoanAdjustLimitBean(EsbBizEnums.RetCodeEnum.SUCCESS.getVALUE(), "交易成功", lmtApplySeq)),
 EsbSysHeadEnums.RetStEnum.SUCCESS.getCode(),
 strings[0],
 strings[1]
 );
 }

 if (!NlsApplyInfoEnums.NlsApplyState.PAUSE.getKey().equals(nlsCreditInfoVO.getApprvSts())) {
 throw new BizException(EsbRetCodeStandard.YWLJCLYC.getValue(), "授信申请状态不是暂停，无法进行后续步骤！");
 }
 //添加插槽阶段值
 addSoltStage(nlsCreditInfoVO);
 //插入两条合同信息到合同表
 insertTwoCtrCont(reqContractSignBean);
 //更新网贷业务过程表
 updateSoltStatus(reqContractSignBean, nlsCreditInfoVO, lmtApplySeq);
 //更新授信状态为通过
 updateCreditStatus(nlsCreditInfoVO);
 //更新授信额度状态为“签订中”
 this.updLmtSts(lmtApplySeq);
 //发送请求到暂停主题队列
 producerService.sendMsg(new Message(TopicEnums.QUEUE_TASK_PAUSE_CTRSIGN_TOPIC.getTopicId(), TagEnums.TAG_QUEUE_PAUSE_CTRSIGN_TASK.getTagId(),
 lmtApplySeq, JSON.toJSONString(nlsCreditInfoVO).getBytes("UTF-8")));
 return EsbRespServiceBeanCreator.buildesbRespServiceBean(
 esbReqServiceBean,
 JSON.toJSONString(buildRespLoanAdjustLimitBean(EsbBizEnums.RetCodeEnum.SUCCESS.getVALUE(), "交易成功", lmtApplySeq)),
 EsbSysHeadEnums.RetStEnum.SUCCESS.getCode(),
 EsbBizEnums.RetCodeEnum.SUCCESS.getVALUE(),
 "交易成功"
 );
 } catch (BizException e) {
 logger.error("***********调用合同要素查询接口处理失败," + e.getMessage() + "**************");
 return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean,
 JSONObject.toJSONString(buildRespLoanAdjustLimitBean(e.getErrorCode(), e.getMessage(), lmtApplySeq)),
 EsbSysHeadEnums.RetStEnum.FAILURE.getCode(),
 e.getErrorCode(),
 e.getMessage());
 } catch (Exception e) {
 logger.error("***********合同签订服务接口处理失败!" + e.getMessage() + "***********");
 return EsbRespServiceBeanCreator.buildesbRespServiceBean(
 esbReqServiceBean,
 JSON.toJSONString(buildRespLoanAdjustLimitBean(EsbRetCodeStandard.OTHERS_EXCEPTION.getValue(), e.getMessage(), lmtApplySeq)),
 EsbSysHeadEnums.RetStEnum.FAILURE.getCode(),
 EsbRetCodeStandard.OTHERS_EXCEPTION.getValue(),
 e.getMessage()
 );
 } finally {
 logger.info("***********合同签订服务结束......授信申请流水号为：" + lmtApplySeq + "***********");
 TraceUtil.clear();
 }
 }
 */
    /**
     * 签完合同后发送短信给客户
     *
     * @param lmtContNo 授信协议编号
     */
    private final void sendCtrMsg(String lmtContNo,String mobileNo) {
        String msg = "尊敬的客户：您已与广州银行签订授信额度编号为" + lmtContNo + "的电子合同。详情请咨询我行24小时客服热线96699。";
        final ReqSedLetterBean reqSedLetterBean = new ReqSedLetterBean();
        reqSedLetterBean.setMblNo(mobileNo);
        reqSedLetterBean.setCntntInf(msg);
        try {
            sedLetterInformService.sendLetter(reqSedLetterBean);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("普税贷授信合同签订下发短信异常：", e);
        }
    }

    private void updateCreditStatus(NlsCreditInfoVO nlsCreditInfoVO) {
        nlsCreditInfoVO.setApprvSts(NlsApplyInfoEnums.NlsApplyState.PASS.getKey());
        int num = nlsCreditInfoService.updateByPk(nlsCreditInfoVO);
        if (num == -1) {
            logger.error("************更新授信状态异常！************");
        } else {
            logger.info("************更新授信状态成功！************");
        }
    }

    private void addSoltStage(NlsCreditInfoVO nlsCreditInfoVO) {
        nlsCreditInfoVO.setSoltStage(PrdAdaptedSoltEnums.SoltStageEnum.CREDIT.getVALUE());

    }

    private NlsCreditInfoVO getApprvSts(String lmtApplySeq) {
        NlsCreditInfoVO querynlsCreditInfo = nlsCreditInfoService.queryByLmtApplySeq(lmtApplySeq);
        return querynlsCreditInfo;
    }

    private void updateSoltStatus(ReqContractSignBean reqContractSignBean, NlsCreditInfoVO querynlsCreditInfo, String lmtApplySeq) throws Exception {
        logger.info("************查询网贷业务过程表************");
        try {
            NlsProcessBizVO inNlsProcessBizVo = new NlsProcessBizVO();
            inNlsProcessBizVo.setApplySeq(lmtApplySeq);
            NlsProcessBizVO queryNlsProcessBizVO = Optional.ofNullable(nlsProcessBizService.queryByPk(inNlsProcessBizVo)).orElseThrow(() -> new Exception("不存在的网贷业务过程！"));
            Objects.requireNonNull(queryNlsProcessBizVO);
            /** 队列任务状态 */
            inNlsProcessBizVo.setQueueTaskState(QueueTaskEnums.QueueTaskStateEnum.EXECUTORY.getCode());
            /** 最后修改时间 */
            inNlsProcessBizVo.setLastModifyTime(DateUtility.getCurrAppDateTimeString());
            int num = nlsProcessBizService.updateByPk(inNlsProcessBizVo);
            if (-1 == num) {
                throw new BizException(EsbRetCodeStandard.SJCLYC.getValue(), "更新网贷业务过程表异常!");
            } else {
                logger.info("************更新网贷业务过程表成功！************");
            }
        } catch (Exception e) {
            logger.info("************数据处理异常！" + e.getMessage() + "************");
            throw e;
        }
    }

    /**
     * 更新授信额度状态为“签订中”
     *
     * @author qiuyf
     * @version 0.1 初始为0.1,后续变更则修改
     * @since 2019年7月3日 上午11:11:28
     */
    private void updLmtSts(String lmtApplySeq) throws BizException {
        LmtPrdContVO lmtPrdContVO = lmtPrdContService.qryLmtPrdContByLmtApplySeq(lmtApplySeq);
        if (Objects.isNull(lmtPrdContVO)) {
            throw new BizException(EsbRetCodeStandard.WFJKYWGZ.getValue(), "授信流水号【" + lmtApplySeq + "】不在授信协议信息");
        }
        lmtPrdContVO.setLmtStatus(ConsoleConstant.LIMIT_STS_04);
        int num = lmtPrdContService.updateByPk(lmtPrdContVO);
        if (num < 0) {
            throw new BizException(EsbRetCodeStandard.SJCLYC.getValue(), "更新授信额度状态失败！");
        }
    }

    /**
     * TODO 插入两条合同信息到合同表<br>
     *
     * @throws Exception
     * @author wanglihua
     * @date 2019年5月10日 下午5:45:09
     * @version 0.1
     * @since 2019年5月10日 下午5:45:09
     */
    private void insertTwoCtrCont(ReqContractSignBean reqContractSignBean) throws Exception {
        logger.info("************开始向合同表插入两条数据！************");
        CtrLoanContVO ctrLoanContVO = new CtrLoanContVO();
        //授信合同
        ctrLoanContVO.setContNo("HT" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + RandomCodeUtils.generateMixed(6));//合同编号
        ctrLoanContVO.setSerno(reqContractSignBean.getCrdtAppFlowNo());//授信申请流水号
        ctrLoanContVO.setLmtContNo(reqContractSignBean.getCrdAgrmNo());//授信协议编号
        ctrLoanContVO.setContType(ConsoleConstant.CONT_TYPE_01);//合同类型
        ctrLoanContVO.setCusName(reqContractSignBean.getCustNm());//客户名称
        ctrLoanContVO.setCertType(reqContractSignBean.getCertTp());//证件类型
        ctrLoanContVO.setCertCode(reqContractSignBean.getCertNo());//证件号码
        ctrLoanContVO.setContAmt(StringUtil.isNullorBank(reqContractSignBean.getRMBLwrcs()) ? BigDecimal.ZERO : new BigDecimal(reqContractSignBean.getRMBLwrcs()));//合同金额
        ctrLoanContVO.setTermTimeType(reqContractSignBean.getLoanTrm());//期限时间类型
        ctrLoanContVO.setLoanTerm(StringUtil.isNullorBank(reqContractSignBean.getCrdtDt()) ? BigDecimal.ZERO : new BigDecimal(reqContractSignBean.getCrdtDt()));//期限
        ctrLoanContVO.setContStartDt(DateUtility.format8To10(reqContractSignBean.getCrdStrtYr() + reqContractSignBean.getCrdStrtMnth() + reqContractSignBean.getCrdStrtDay()));//借据起始日
        ctrLoanContVO.setContEndDt(DateUtility.format8To10(reqContractSignBean.getCrdEndYr() + reqContractSignBean.getCrdEndMnth() + reqContractSignBean.getCrdEndDay()));//借据到期日
        ctrLoanContVO.setCalFloatingRate(StringUtil.isNullorBank(reqContractSignBean.getUpFltIntRt()) ? BigDecimal.ZERO : new BigDecimal(reqContractSignBean.getUpFltIntRt()));//利率浮动比
        ctrLoanContVO.setRepaymentMode(reqContractSignBean.getRpyMd());//还款方式
        ctrLoanContVO.setSignDate(reqContractSignBean.getSgnDt());//合同签订日期
        ctrLoanContVO.setContState("101");//合同状态
        logger.info("************向合同表插入的授信合同为：" + "【" + ctrLoanContVO.toString() + "】");
        int count1 = ctrLoanContService.insertCtrLoanCont(ctrLoanContVO);
        if (count1 == -1) {
            throw new BizException(EsbRetCodeStandard.SJCLYC.getValue(), "插入授信合同异常！");
        } else {
            logger.info("************向合同表插入授信合同成功！************");
        }
        //借款合同
        ctrLoanContVO.setContNo("HT" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + RandomCodeUtils.generateMixed(6));//合同编号
        ctrLoanContVO.setContType(ConsoleConstant.CONT_TYPE_02);
        logger.info("************向合同表插入的借款合同为：" + "【" + ctrLoanContVO.toString() + "】");
        int count2 = ctrLoanContService.insertCtrLoanCont(ctrLoanContVO);
        if (count2 == -1) {
            throw new BizException(EsbRetCodeStandard.SJCLYC.getValue(), "插入借款合同异常！");
        } else {
            logger.info("************向合同表插入借款合同成功！************");
        }
    }

    private static RespSedCreditBean buildRespLoanAdjustLimitBean(String retStCd, String rtnMsg, String lmtApplySeq) {
        logger.debug("*********组装额度合同签订服务接口响应bean开始...授信申请流水号：" + lmtApplySeq);
        RespSedCreditBean respSedCreditBean = new RespSedCreditBean();
        respSedCreditBean.setRetCd(retStCd);
        respSedCreditBean.setRetMsg(rtnMsg);
        logger.debug("{*********组装合同签订服务接口响应bean结束！授信申请流水号：" + lmtApplySeq + ",返回码:" + retStCd + ",返回信息:" + rtnMsg + "**********}");
        return respSedCreditBean;
    }

    @Autowired
    @Qualifier("ctrLoanContService")
    private CtrLoanContService ctrLoanContService;

    @Autowired
    @Qualifier("nlsProcessBizService")
    private NlsProcessBizService nlsProcessBizService;

    @Autowired
    @Qualifier("nlsCreditInfoService")
    private NlsCreditInfoService nlsCreditInfoService;

    @Autowired
    @Qualifier("producerService")
    private MQProducerMessageClient producerService;

    @Autowired
    @Qualifier("lmtPrdContService")
    private LmtPrdContService lmtPrdContService;

    @Autowired
    @Qualifier("dbSeqService")
    private SequenceService sequenceService;

    @Autowired
    @Qualifier("sedLetterInformService")
    private SedLetterInformService sedLetterInformService;
}
